#pragma once

#include <afxcview.h>
#include <vector>
#include <map>



class CTimeline;
class CTransformDoc;


class CFlag
{
public:
	enum Status
	{
		eUnSelect = -1,
		ePreSelecting,
		eSelecting
	};

	CFlag();
	virtual~ CFlag();

	void						Draw(CDC* pDC, int iScrollX);
	CRect						PreSelect();
	void						UnSelect();

	void						SetPosition(POINT pt) { m_oPosition = pt; }
	POINT						GetPosition() { return m_oPosition; }
	void						SetStatus(Status status) { m_eStatus = status; }
	Status						GetStatus() { return m_eStatus; }

private:
	POINT						m_oPosition;
	int							m_iScrollX;
	Status						m_eStatus;
};


typedef std::map<CString, CFlag*> FlagMap;
typedef std::pair<CString, CFlag*> FlagPair;
class CFlagMap
{
public:
	CFlagMap();
	virtual~ CFlagMap();

	void						SetScroll(int x) { m_iScroll = x; }
	void						Add(CFlag* pFlag);
	void						DeleteAll();
	void						DrawAll(CDC* pDC);
	CFlag*						Find(POINT pt);
	CFlag*						Find(CString& strID);
	void						DeleteAllSelection();

private:
	FlagMap						m_oFlagMap;
	int							m_iScroll;
	CString						m_strSelectedKey;
};


class CSelectingRect
{
public:
	CSelectingRect();
	virtual~ CSelectingRect();

	enum Status
	{
		eNone = -1,
		ePreSelecting,
		eSelecting
	};

	void						Draw(CDC* pDC);

	void						SetRect(int x1, int y1, int x2, int y2);
	void						SetMaxRect(LPRECT lRect) { m_maxRect = lRect; }
	void						SetScroll(int scroll) { m_iScroll = scroll; }
	void						SetStatus(Status eStatus) { m_eStatus = eStatus; }

	POINT						GetCenter() { return m_rect.CenterPoint(); }
	CRect						GetRect();
	Status						GetStatus() { return m_eStatus; }

	bool						IsSelecting(POINT pt);
	bool						IsExisted() { return m_bExisted; }


	void						Move(int DeltaX);
	void						MoveTo(int x);
	int							WToU(int x);

private:
	CRect						m_rect;
	bool						m_bExisted;
	CRect						m_maxRect;
	Status						m_eStatus;
	int							m_iScroll;
};


class CGraduation
{
public:
	CGraduation();
	virtual~ CGraduation();

	void						Draw(CDC* pDC);
	void						SetScroll(int scroll) { m_iScroll = scroll; }
	int							WToU(int x);
	void						SetFrameCount(long lCount) { m_iFrameCount = lCount; }
	void						SetStartPt(POINT pt) { m_oGraduationStartPt = pt; }

	int							OnSelect(int sourceX);

	int							GetIndex(int x);

private:
	POINT						m_oGraduationStartPt;
	int							m_UnitSpace;
	int							m_iFrameCount;
	int							m_iScroll;
};


class CUILine
{
public:
	CUILine();
	virtual~ CUILine();


	void						Draw(CDC* pDC);

	void						SetStartPt(POINT pt) { m_startPt = pt; }
	void						SetEndPt(POINT pt) { m_endPt = pt; }

	long						GetHeight() { return m_startPt.y; }

private:
	POINT						m_startPt;
	POINT						m_endPt;
};

typedef std::vector<CUILine*> UILines;

class CTimelineView : public CScrollView
{
protected: // create from serialization only
	CTimelineView();
	DECLARE_DYNCREATE(CTimelineView)

	virtual ~CTimelineView();

// Attributes
public:
	void							SetDoc(CTransformDoc* pDoc)
	{ m_pDoc = pDoc; }
	void							SetFlagAddingStatus(bool bAddingStatus)
	{ m_bFlagAddingStatus = bAddingStatus; }

	void							SetTimelineObject(CTimeline* pTimelineObj) { m_pTimeline = pTimelineObj; }


// Operations
public:
	void							UpdateView();

// Overrides
public:
	virtual BOOL					PreCreateWindow(CREATESTRUCT& cs);
	

// Generated message map functions
protected:
	virtual void					OnDraw(CDC* pDC);  // overridden to draw this view
	virtual void					OnInitialUpdate();

	afx_msg int						OnCreate(LPCREATESTRUCT lpCreateStruct);
	afx_msg void					OnDestroy();
	afx_msg void					OnSize(UINT nType, int cx, int cy);
	afx_msg void					OnLButtonDown(UINT nFlags, CPoint point);
	afx_msg void					OnLButtonUp(UINT nFlags, CPoint point);
	afx_msg void					OnRButtonDblClk(UINT nFlags, CPoint point);
	afx_msg void					OnMouseMove(UINT nFlags, CPoint point);
	afx_msg void					OnMButtonDown(UINT nFlags, CPoint point);
	afx_msg void					OnMButtonUp(UINT nFlags, CPoint point);
	afx_msg BOOL					OnMouseWheel(UINT nFlags, short zDelta, CPoint pt);
	afx_msg void					OnRButtonDown(UINT nFlags, CPoint point);
	afx_msg void					OnRButtonUp(UINT nFlags, CPoint point);
	afx_msg void					OnTimer(UINT_PTR nIDEvent);
	afx_msg void					OnHScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar);
	afx_msg void					OnVScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar);
	afx_msg void					OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags);
	DECLARE_MESSAGE_MAP()

	void							CreateKnot(int row, int column);
	int								GetRowIndex(long y);
	int								GetColumnIndex(long x);


private:
	void							InitializeGraphicsEntities(long row, long frames);


	void							Draw(CDC* pDC);
	void							DrawGraduation(CDC* pDC);
	void							DrawSelectingRect(CDC* pDC);
	void							DrawLines(CDC* pDC);
	void							DrawFlags(CDC* pDC);
	void							RefreshRect(int iMinX, int iMaxX);

	int								AdjustYAsLine(int sourceY);
	int								UToW(int x);
	int								WToU(int x);

	CTransformDoc*					m_pDoc;
	CSelectingRect					m_oSelectingRect;
	CGraduation						m_oGraduation;
	POINT							m_oSelectedPt;
	UILines							m_oUILines;

	bool							m_bInitialized;
	int								m_Height;
	int								m_Width;
	int								m_minX;
	int								m_ScrollX;
	int								m_ScrollY;

	CFlagMap						m_oFlagMap;
	bool							m_bFlagAddingStatus;
	CFlag*							m_pPreSelecingFlag;

	CTimeline*						m_pTimeline;
};